package com.quanyan.user.service.impl;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.lefu.commons.utils.Page;
import com.quanyan.api.APIResponse;
import com.quanyan.comment.enums.TaskEnum;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.user.cache.MyRedisTemplate;
import com.quanyan.user.constants.UserConstants;
import com.quanyan.user.mapper.NewsPraiseMapper;
import com.quanyan.user.mapper.TbNewsDetailsMapper;
import com.quanyan.user.mapper.TbNewsPraiseMapper;
import com.quanyan.user.model.db.*;
import com.quanyan.user.model.vo.request.ReqNewsPraise;
import com.quanyan.user.model.vo.request.ReqUserPraise;
import com.quanyan.user.model.vo.request.UnReadParam;
import com.quanyan.user.model.vo.response.ImageObj;
import com.quanyan.user.model.vo.response.RespDynamicDetail;
import com.quanyan.user.model.vo.response.RespNewsPraise;
import com.quanyan.user.mq.UserTaskMsg;
import com.quanyan.user.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by Administrator on 2016/11/15.
 */
@Service
public class NewsPraiseServiceImpl implements NewsPraiseService {

    private static final Logger logger = LoggerFactory.getLogger(NewsPraiseServiceImpl.class);

    @Autowired
    private TbNewsDetailsMapper tbNewsDetailsMapper;

    @Autowired
    private TbNewsPraiseMapper tbNewsPraiseMapper;

    @Autowired
    private NewsPraiseMapper newsPraiseMapper;

    @Autowired
    private UserFollowService userFollowService;

    @Autowired
    private UserFriendService userFriendService;

    @Autowired
    private SendMsgService sendMsgService;

    @Autowired
    private UserQueryService userQueryService;

    @Autowired
    private MyRedisTemplate myRedisTemplate;

    @Autowired
    private NewsImagesService newsImagesService;

    @Autowired
    private UserDynamicService userDynamicService;

    @Autowired
    private NewsUnReadService newsUnReadService;



    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public APIResponse praise(ReqUserPraise reqUserPraise) {
        logger.info("开始点赞{}", reqUserPraise.toString());
        Integer uid = reqUserPraise.getUid();
        Integer dynamicDetailsId = reqUserPraise.getDynamicDetailsId();
        TbNewsDetails tbNewsDetails = tbNewsDetailsMapper.selectByPrimaryKey(dynamicDetailsId); //动态
        if (tbNewsDetails != null && tbNewsDetails.getIsDelete() == Constants.IS_DELETE_FALSE) { // 动态存在并且未删除
            /*====用户点赞====*/
            TbNewsPraiseExample tbNewsPraiseExample = new TbNewsPraiseExample();
            TbNewsPraiseExample.Criteria criteria = tbNewsPraiseExample.createCriteria();
            criteria.andUidEqualTo(uid);
            criteria.andNewsIdEqualTo(dynamicDetailsId);
            List<TbNewsPraise> lstPraise = tbNewsPraiseMapper.selectByExample(tbNewsPraiseExample);
            if (lstPraise != null && lstPraise.size() > 0) { //赞存在
                TbNewsPraise tbNewsPraise = lstPraise.get(0);
                if (tbNewsPraise.getIsDelete().byteValue() == Constants.IS_DELETE_FALSE && tbNewsPraise.getType() == UserConstants.PRAISE_ADD) { // 未删除并且是点赞状态
                    logger.info("已经点赞！");
                    return APIResponse.returnSuccess("已经点赞!");
                } else {
                    logger.info("赞存在，开始更改状态");
                    tbNewsPraise.setIsDelete(Constants.IS_DELETE_FALSE);
                    tbNewsPraise.setType(UserConstants.PRAISE_ADD);
                    tbNewsPraiseMapper.updateByPrimaryKeySelective(tbNewsPraise);

                    tbNewsDetails.setSumPraises(tbNewsDetails.getSumPraises() + 1); //增加点赞数
                    tbNewsDetailsMapper.updateByPrimaryKeySelective(tbNewsDetails);
                    String key = UserConstants.getDynamicPraiseKey(dynamicDetailsId);
                    List<RespNewsPraise> lst = (List<RespNewsPraise>) myRedisTemplate.get(key);
                    if (lst != null)
                        myRedisTemplate.delteKey(key);
                    // 做任务
                    logger.info("点赞成功");
                    return userDynamicService.dynamicDetail(uid, dynamicDetailsId);
                }
            } else {
                logger.info("赞不存在，开始插入！");
                TbNewsPraise tbNewsPraise = new TbNewsPraise();
                tbNewsPraise.setType(UserConstants.PRAISE_ADD);
                tbNewsPraise.setUid(uid);
                tbNewsPraise.setIsDelete(Constants.IS_DELETE_FALSE);
                tbNewsPraise.setNewsId(dynamicDetailsId);
                tbNewsPraise.setMemo("");
                tbNewsPraise.setCreateTime(new Date());
                tbNewsPraiseMapper.insert(tbNewsPraise);
                logger.info("点赞成功");
                tbNewsDetails.setSumPraises(tbNewsDetails.getSumPraises() + 1); //增加点赞数
                tbNewsDetailsMapper.updateByPrimaryKeySelective(tbNewsDetails);

                String key = UserConstants.getDynamicPraiseKey(dynamicDetailsId);
                List<RespNewsPraise> lst = (List<RespNewsPraise>) myRedisTemplate.get(key);
                if (lst != null)
                    myRedisTemplate.delteKey(key);

                // 点赞任务
                UserTaskMsg userTaskMsg = new UserTaskMsg();
                userTaskMsg.setUid(uid);
                userTaskMsg.setTaskId(TaskEnum.TASK_ENUM__I_CLICK_LIKE.getId());
                sendMsgService.sendUserTaskMsg(userTaskMsg);

                TbUser tbUser = userQueryService.getUser(uid);
                List<ImageObj> lstImg = newsImagesService.getDynamicImages(dynamicDetailsId);
                String tempImgUrl = "";
                if (lstImg != null && lstImg.size() > 0)
                    tempImgUrl = lstImg.get(0).getImageUrl();
                //sendMsgService.pushDynamicMsg(tbUser, tbNewsDetails.getUid(), null, dynamicDetailsId, null, BoxType.PRAISE_MSG.value(), tempImgUrl);
                if(reqUserPraise.getUid().intValue() != tbNewsDetails.getUid().intValue()){//给自己点赞
                    //未读消息数
                    UnReadParam unReadParam = new UnReadParam();
                    unReadParam.setUid(tbNewsDetails.getUid());
                    unReadParam.setType(NewsUnReadService.NewsUnReadType.praise);
                    unReadParam.setNewsId(dynamicDetailsId);
                    unReadParam.setfUid(uid);
                    unReadParam.setDynamicImg(tempImgUrl);
                    newsUnReadService.addNewsUnRead(unReadParam);
                }
                return userDynamicService.dynamicDetail(uid, dynamicDetailsId);
            }
        }
        logger.info("此条动态不存在");
        return APIResponse.returnFail("此条动态不存在！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public APIResponse praiseCancel(ReqUserPraise reqUserPraise) {
        logger.info("开始点赞{}", reqUserPraise.toString());
        Integer uid = reqUserPraise.getUid();
        Integer dynamicDetailsId = reqUserPraise.getDynamicDetailsId();
        logger.info("开始取消点赞uid:{},dynamicDetailsId:{}", uid, dynamicDetailsId);
        TbNewsDetails tbNewsDetails = tbNewsDetailsMapper.selectByPrimaryKey(dynamicDetailsId); //动态
        if (tbNewsDetails != null && tbNewsDetails.getIsDelete() == Constants.IS_DELETE_FALSE) { // 动态存在并且未删除
            /*====用户取消点赞====*/
            TbNewsPraiseExample tbNewsPraiseExample = new TbNewsPraiseExample();
            TbNewsPraiseExample.Criteria criteria = tbNewsPraiseExample.createCriteria();
            criteria.andUidEqualTo(uid);
            criteria.andNewsIdEqualTo(dynamicDetailsId);
            criteria.andTypeEqualTo(UserConstants.PRAISE_ADD);
            criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
            List<TbNewsPraise> lstPraise = tbNewsPraiseMapper.selectByExample(tbNewsPraiseExample);
            if (lstPraise != null && lstPraise.size() > 0) { //赞存在
                TbNewsPraise tbNewsPraise = lstPraise.get(0);
                tbNewsPraise.setType(UserConstants.PRAISE_CANCEL);
                tbNewsPraiseMapper.updateByPrimaryKeySelective(tbNewsPraise);

                tbNewsDetails.setSumPraises(tbNewsDetails.getSumPraises() - 1); //减少点赞数
                tbNewsDetailsMapper.updateByPrimaryKeySelective(tbNewsDetails);

                String key = UserConstants.getDynamicPraiseKey(dynamicDetailsId);
                List<RespNewsPraise> lst = (List<RespNewsPraise>) myRedisTemplate.get(key);
                if (lst != null)
                    myRedisTemplate.delteKey(key);

                logger.info("取消点赞成功！");
                return userDynamicService.dynamicDetail(uid, dynamicDetailsId);
            }
            return APIResponse.returnFail("已经取消点赞！");
        }
        logger.info("此条动态不存在");
        return APIResponse.returnFail("此条动态不存在！");


    }


    @Override
    public APIResponse<PageObj<List<RespNewsPraise>>> praiseList(ReqNewsPraise reqNewsPraise) {
        Page<List<RespNewsPraise>> page = this.getDynamicPraiseList(reqNewsPraise);
        PageObj<List<RespNewsPraise>> result = PageObj.create(page.getTotalResult(), page.getCurrentPage(), page.getShowCount(), page.getObject());
        return APIResponse.returnSuccess(result);
    }

    public List<TbNewsPraise> findNewsPraiseList(Integer uid, List<Integer> lstNewsId) {
        if (lstNewsId != null && lstNewsId.size() > 0) {
            TbNewsPraiseExample tbNewsPraiseExample = new TbNewsPraiseExample();
            TbNewsPraiseExample.Criteria criteria = tbNewsPraiseExample.createCriteria();
            criteria.andNewsIdIn(lstNewsId);
            criteria.andUidEqualTo(uid);
            criteria.andTypeEqualTo(praise_true);
            criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
            return tbNewsPraiseMapper.selectByExample(tbNewsPraiseExample);
        }
        return null;
    }


    public Map<Integer, TbNewsPraise> findNewsPraiseMap(Integer uid, List<Integer> lstNewsId) {
        List<TbNewsPraise> lst = this.findNewsPraiseList(uid, lstNewsId);
        Map<Integer, TbNewsPraise> map = new HashMap<>();
        if (lst != null && lst.size() > 0) {
            map = Maps.uniqueIndex(lst, this.indexOriginDtoByVendorItemId());
        }
        return map;
    }


    public Function<TbNewsPraise, Integer> indexOriginDtoByVendorItemId() {
        return new Function<TbNewsPraise, Integer>() {
            @Override
            public Integer apply(TbNewsPraise input) {
                return input.getNewsId();
            }
        };
    }


    @Override
    public Page<List<RespNewsPraise>> getDynamicPraiseList(ReqNewsPraise reqNewsPraise) {
        Integer uid = reqNewsPraise.getUid();
        Integer dynamicDetailsId = reqNewsPraise.getDynamicDetailsId();
        logger.info("开始获取动态点赞列表:{}", reqNewsPraise.toString());
        TbNewsDetails tbNewsDetails = tbNewsDetailsMapper.selectByPrimaryKey(dynamicDetailsId); //动态
        List<RespNewsPraise> lstPraise = new ArrayList<>();
        /****========获取点赞列表======****/
        Page page = new Page();
        int pageIndex = reqNewsPraise.getPageNum() + 1;
        page.setCurrentPage(pageIndex);
        page.setShowCount(reqNewsPraise.getPageSize());

        if (tbNewsDetails != null && tbNewsDetails.getIsDelete() != Constants.IS_DELETE_TRUE) { // 动态存在并且未删除
            Map<String, Object> map = new HashMap<>();
            lstPraise = newsPraiseMapper.findAllUserPraise(page, dynamicDetailsId);
            if (pageIndex > page.getTotalPage()) {
                lstPraise = new ArrayList<>();
                page.setTotalPage(0);
                page.setTotalResult(0);
            }

            if (lstPraise != null && lstPraise.size() > 0) {
                List<Integer> lst = new ArrayList<>(); //点赞的用户
                for (RespNewsPraise tbNewsPraise : lstPraise) {
                    lst.add(tbNewsPraise.getUid());
                }

                if (uid != null) {
                    if (lst.size() > 0) {
                        List<TbUserFriend> lstUfr = userFriendService.batchUserFriendService(uid, lst); // 查看是否是好友
                        Map<Integer, TbUserFollow> mapUf = userFollowService.batchUserFollowMap(uid, lst);
                        Map<Integer, TbUserFriend> mapUfr = new HashMap<>();
                        for (TbUserFriend uf : lstUfr) {
                            mapUfr.put(uf.getFriendId(), uf);
                        }
                        for (RespNewsPraise respNesPraise : lstPraise) {
                            if (mapUf.containsKey(respNesPraise.getUid()))
                                respNesPraise.setIsFollow((byte) 1);
                            else
                                respNesPraise.setIsFollow((byte) 0);

                            if (mapUfr.containsKey(respNesPraise.getUid()))
                                respNesPraise.setIsFriend((byte) 1);
                            else
                                respNesPraise.setIsFriend((byte) 0);
                        }
                    }
                }
            }
        }
        page.setObject(lstPraise);
        return page;
    }

    public List<RespNewsPraise> findAllPraiseByNewsId(List<RespDynamicDetail> lst) {
        List<RespDynamicDetail> lstDbDynamic = new ArrayList<>();
        for (RespDynamicDetail respDynamicDetail : lst) {
            String key = UserConstants.getDynamicPraiseKey(respDynamicDetail.getId());
            List<RespNewsPraise> lstPraise = (List<RespNewsPraise>) myRedisTemplate.get(key);
            if (lstPraise != null) {
                respDynamicDetail.getPraises().addAll(lstPraise);
            } else {
                lstDbDynamic.add(respDynamicDetail);
            }
        }

        if (lstDbDynamic.size() > 0) {
            List<RespNewsPraise> lstTb = newsPraiseMapper.findPraiseByNewsId(lstDbDynamic);
            /****===========按动态分组=============****/
            ImmutableSet digits = ImmutableSet.of(lstTb.toArray());
            Function<RespNewsPraise, Integer> dynamicPraise = new Function<RespNewsPraise, Integer>() {
                @Override
                public Integer apply(RespNewsPraise respNewsPraise) {
                    return respNewsPraise.getNewsId();
                }
            };
            ImmutableListMultimap<Integer, RespNewsPraise> lstDynamicPraise = Multimaps.index(digits, dynamicPraise); //分组后
            for (RespDynamicDetail respDynamicDetail : lst) {
                List<RespNewsPraise> lstDb = lstDynamicPraise.get(respDynamicDetail.getId());
                if (lstDb != null && lstDb.size() > 0) {
                    String key = UserConstants.getDynamicPraiseKey(respDynamicDetail.getId());
                    myRedisTemplate.set(key, lstDb, 7);
                }
            }
            return newsPraiseMapper.findPraiseByNewsId(lst);
        }

        return null;
    }


    public APIResponse videoPraise(ReqUserPraise reqUserPraise){
        logger.info("start video praise add :{}",reqUserPraise.toString());
        Integer uid = reqUserPraise.getUid();
        Integer videoId = reqUserPraise.getDynamicDetailsId();

        TbNewsPraiseExample tbNewsPraiseExample = new TbNewsPraiseExample();
        TbNewsPraiseExample.Criteria criteria = tbNewsPraiseExample.createCriteria();
        criteria.andUidEqualTo(uid);
        criteria.andNewsIdEqualTo(videoId);

        List<TbNewsPraise> lstNewsPraise =  tbNewsPraiseMapper.selectByExample(tbNewsPraiseExample);
        if (lstNewsPraise != null && lstNewsPraise.size() > 0 ){
            TbNewsPraise tbNewsPraise = lstNewsPraise.get(0);
            if(tbNewsPraise.getIsDelete().byteValue() == Constants.IS_DELETE_FALSE && tbNewsPraise.getType() == UserConstants.PRAISE_ADD){
                logger.info("已经点赞");
                return APIResponse.returnFail("已经点赞");
            }else {
                TbNewsPraise updateTbNewsPraise = new TbNewsPraise();
                updateTbNewsPraise.setId(tbNewsPraise.getId());
                updateTbNewsPraise.setType(UserConstants.PRAISE_ADD);
                tbNewsPraiseMapper.updateByPrimaryKeySelective(updateTbNewsPraise);
                logger.info("点赞成功！");
                return APIResponse.returnSuccess();
            }
        }else {
            logger.info("赞不存在，开始插入！");
            TbNewsPraise tbNewsPraise = new TbNewsPraise();
            tbNewsPraise.setType(UserConstants.PRAISE_ADD);
            tbNewsPraise.setUid(uid);
            tbNewsPraise.setIsDelete(Constants.IS_DELETE_FALSE);
            tbNewsPraise.setNewsId(videoId);
            tbNewsPraise.setMemo("");
            tbNewsPraise.setCreateTime(new Date());
            tbNewsPraiseMapper.insert(tbNewsPraise);
            logger.info("点赞成功！");
            return APIResponse.returnSuccess();
        }

    }

    public APIResponse videoPraiseCancel(ReqUserPraise reqUserPraise){
        logger.info("start video praise add :{}",reqUserPraise.toString());
        Integer uid = reqUserPraise.getUid();
        Integer videoId = reqUserPraise.getDynamicDetailsId();

        TbNewsPraiseExample tbNewsPraiseExample = new TbNewsPraiseExample();
        TbNewsPraiseExample.Criteria criteria = tbNewsPraiseExample.createCriteria();
        criteria.andUidEqualTo(uid);
        criteria.andNewsIdEqualTo(videoId);

        List<TbNewsPraise> lstNewsPraise =  tbNewsPraiseMapper.selectByExample(tbNewsPraiseExample);
        if (lstNewsPraise != null && lstNewsPraise.size() > 0 ){
            TbNewsPraise tbNewsPraise = lstNewsPraise.get(0);
            if(tbNewsPraise.getIsDelete().byteValue() == Constants.IS_DELETE_FALSE && tbNewsPraise.getType() == UserConstants.PRAISE_CANCEL){
                logger.info("赞已经取消");
                return APIResponse.returnFail("赞已经取消");
            }else {
                TbNewsPraise updateTbNewsPraise = new TbNewsPraise();
                updateTbNewsPraise.setId(tbNewsPraise.getId());
                updateTbNewsPraise.setType(UserConstants.PRAISE_CANCEL);
                tbNewsPraiseMapper.updateByPrimaryKeySelective(updateTbNewsPraise);
                logger.info("赞已经取消！");
                return APIResponse.returnSuccess();
            }
        }else {
            logger.info("赞不存在");
            return APIResponse.returnSuccess();
        }
    }

}
